
#include "Task.hpp"

// 父进程写，子进程读
class Channel
{
private:
    int _wfd;
    int _id;

public:
    Channel(int wfd, int id)
        : _wfd(wfd), _id(id)
    {
    }
    void close_subprocess()
    {
        close(_wfd);
    }
    int get_wfd()
    {
        return _wfd;
    }
    int get_id()
    {
        return _id;
    }
};

void work(int rfd);
void create_ChannelAndSubprocess(std::vector<Channel> *channels, int child_number, work_t work);
int next_channel(std::vector<Channel> &channels);
void send_command(Channel &channel, int option_task);
void ctrl_channel(std::vector<Channel> &channels);
void clean_ChannelAndSubprocess(std::vector<Channel> *channels);
int main(int argv, char* argc[])
{
    std::vector<Channel> channels;
    load_task();

    if (argv != 2)
        return -1;
    int num = std::stoi(argc[1]);
    // 1、创建信道和子进程
    create_ChannelAndSubprocess(&channels, num, work);

    // 2、通过信道控制子进程
    ctrl_channel(channels);

    // 3、回收管道和子进程
    clean_ChannelAndSubprocess(&channels);
    return 0;
}

void create_ChannelAndSubprocess(std::vector<Channel> *channels, int child_number, work_t work)
{
    for (int i = 0; i < child_number; i++)
    {
        int pipefd[2] = {0};
        int exit_code = pipe(pipefd);
        if (exit_code < 0)
        {
            std::cout << "errno : " << exit_code << std::endl;
            exit(1);
        }
        pid_t id = fork();
        if (id == 0)
        {
            // child;
            close(pipefd[1]);
            work(pipefd[0]);
            exit(0);
        }
        // father
        close(pipefd[0]);

        (*channels).emplace_back(pipefd[1], id);
    }

    std::cout << "创建了：" << channels->size() << "个信道和子进程" << std::endl;
}
int next_channel(std::vector<Channel> &channels)
{
    static int count = 0;
    int option = count;
    count++;
    count %= channels.size();
    return option;
}
void send_command(Channel &channel, int option_task)
{
    write(channel.get_wfd(), &option_task, sizeof(option_task));
}
void ctrl_channel(std::vector<Channel> &channels)
{
    // 选择任务
    srand(time(nullptr));
    int n = task_number;
    while (n -- )
    {
        int option_task = rand() % task.size(); // task[option_task]
        // 选择信道
        int option_channel = next_channel(channels); // channels[option_task]
        // 发送任务
        send_command(channels.at(option_channel), option_task);
        sleep(1);
    }
}
void clean_ChannelAndSubprocess(std::vector<Channel> *channels)
{
    for (auto& channel:*channels)
    {
        channel.close_subprocess();
    }
    for (auto& channel:*channels)
    {
        waitpid(channel.get_id(), 0, 0);
    }
}